/*********************************************************************************************************************
 * COPYRIGHT NOTICE
 * Copyright (c) 2018,逐飞科技
 * All rights reserved.
 * 技术讨论QQ群：	一群：179029047(已满)
 *					二群：244861897(已满)
 *					三群：824575535
 *
 * 以下所有内容版权均属逐飞科技所有，未经允许不得用于商业用途，
 * 欢迎各位使用并传播本程序，修改内容时必须保留逐飞科技的版权声明。
 *
 * @file			zf_spi.c
 * @company			成都逐飞科技有限公司
 * @author			逐飞科技(QQ3184284598)
 * @version			查看doc内version文件 版本说明
 * @Software		IAR 8.3 or MDK 5.24
 * @Taobao			https://seekfree.taobao.com/
 * @date			2020-03-25
 * @note			本文件作为 LPC55S 系列芯片开源库外设文件
					提供 SPI 外设驱动
 ********************************************************************************************************************/

#include "zf_spi.h"
#include "zf_isr.h"

static spi_master_handle_t spi_transfer_handle[8];
static spi_config_t g_spi_data_config[8];
static spi_transfer_t g_spi_transfer_t[8];
 
static volatile uint16_t *FIFOWR_SPI_H16[8] = 															// 这里是 SPI 的 FIFOWR 寄存器高16位地址
{
	((volatile uint16_t *)0x40086E22),																	// SPI0 <FlexCOMM0> FIFOWR
	((volatile uint16_t *)0x40087E22),																	// SPI1 <FlexCOMM1> FIFOWR
	((volatile uint16_t *)0x40088E22),																	// SPI2 <FlexCOMM2> FIFOWR
	((volatile uint16_t *)0x40089E22),																	// SPI3 <FlexCOMM3> FIFOWR
	((volatile uint16_t *)0x4008AE22),																	// SPI4 <FlexCOMM4> FIFOWR
	((volatile uint16_t *)0x40096E22),																	// SPI5 <FlexCOMM5> FIFOWR
	((volatile uint16_t *)0x40097E22),																	// SPI6 <FlexCOMM6> FIFOWR
	((volatile uint16_t *)0x40098E22)																	// SPI7 <FlexCOMM7> FIFOWR
};

//-------------------------------------------------------------------------------------------------------------------
//	@brief		Flex COMM获取 SPI MASTER 默认设置
//	@param		config			FC所选功能的配置参数结构体
//	Sample usage:				zf_spi_master_get_default_config( &spi_master_config );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_master_get_default_config (spi_master_config_t *config)
{
	assert(config != NULL);
	SPI_MasterGetDefaultConfig(config);																	// 获取 Master 模式的默认配置

	config->enableMaster = true;

	config->sselNum = (spi_ssel_t)SPI_SSEL0;															// 默认配置从机目标为 1

	config->sselPol = (spi_spol_t)SPI_SSEL_POLARITY_ALL_LOW;											// 设置片选低电平有效
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		Flex COMM 修改 SPI MASTER 设置
//	@param		config			FC所选功能的配置参数结构体
//	@param		param_index		对应参数的索引
//	@param		data			参数数值
//	Sample usage:				zf_spi_master_param_set( &spi_master_config, SPI_MASTER_PARAM_DELAY_TRANSFER,	0 );	
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_master_param_set  (spi_master_config_t *config, spi_master_param_list param_index, uint32_t data)
{
	switch(param_index)
	{
		case SPI_MASTER_PARAM_LOOP_BACK :																// 测试数据回环回调
			config->enableLoopback = (bool) data;														// 更新使能数据
			break;
		case SPI_MASTER_PARAM_MASTER_ENABLE:
			config->enableMaster = (bool) data;															// 更新使能数据
			break;
		case SPI_MASTER_PARAM_CLOCK_POLARITY :															// 时钟极性
			config->polarity = (spi_clock_polarity_t) data;												// 更新时钟极性选项
			break;
		case SPI_MASTER_PARAM_CLOCK_PHASE :																// 时钟相位
			config->phase = (spi_clock_phase_t) data;													// 更新时钟相位选项
			break;
		case SPI_MASTER_PARAM_DATA_DIRECTION :															// SPI 数据排列方向 MSB/LSB
			config->direction = (spi_shift_direction_t) data;											// 更新数据方向
			break;
		case SPI_MASTER_PARAM_BAUD_RATE :																// SPI 数据传输波特率
			config->baudRate_Bps = data;																// 更新 SPI 传输波特率
			break;
		case SPI_MASTER_PARAM_DATA_WIDTH :																// SPI 单个数据长度
			config->dataWidth = (spi_data_width_t) data;												// 更新单个数据长度
			break;
		case SPI_MASTER_PARAM_SSEL_SELECT:																// 从机选择
			config->sselNum = (spi_ssel_t) data;														// 修改从机选择电平
			break;
		case SPI_MASTER_PARAM_SSEL_POLARITY :															// 从机有效电平
			config->sselPol = (spi_spol_t) data;														// 修改从机选择电平
			break;
		case SPI_MASTER_PARAM_TX_FIFO :																	// TX 缓冲区触发级数
			config->txWatermark = (uint8_t) data;														// 修改接收 TX 触发条例数目
			break;
		case SPI_MASTER_PARAM_RX_FIFO :																	// RX 缓冲区触发级数
			config->rxWatermark = (uint8_t) data;														// 修改接收 RX 触发条例数目
			break;

		case SPI_MASTER_PARAM_DELAY_PRE :																// 断言与传输之间的延时
			config->delayConfig.preDelay = (uint8_t) data;												// 更改断言与传输之间的延时
			break;
		case SPI_MASTER_PARAM_DELAY_POST :																// 传输结束与从机终止之间的延时
			config->delayConfig.postDelay = (uint8_t) data;												// 更改传输结束与从机终止之间的延时
			break;
		case SPI_MASTER_PARAM_DELAY_FRAME :																// 帧延时
			config->delayConfig.frameDelay = (uint8_t) data;											// 更改帧延时
			break;
		case SPI_MASTER_PARAM_DELAY_TRANSFER :															// 传输延时
			config->delayConfig.transferDelay = (uint8_t) data;											// 更改传输延时
			break;
		default:
			break;
	}
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		Flex COMM 设置 SPI 数据格式
//	@param		flexCommIndex	所选 FC 标识
//	@param		config			FC所选功能的配置参数结构体
//	Sample usage:				zf_spi_master_set_spi_dataformat( FLEX_COMM0, flexcomm_spi_master_config_1 );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_master_set_spi_dataformat (flexcomm_index_list flexCommIndex, spi_master_config_t *config)
{
	g_spi_data_config[flexCommIndex].dataWidth = config->dataWidth;
	g_spi_data_config[flexCommIndex].sselNum = config->sselNum;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		Flex COMM获取 SPI SLAVE 默认设置
//	@param		config			FC所选功能的配置参数结构体
//	Sample usage:				zf_spi_slave_get_default_config( &spi_slave_config );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_slave_get_default_config (spi_slave_config_t *config)
{
	assert(config != NULL);
	SPI_SlaveGetDefaultConfig(config);																	// 获取 Slave 模式的默认配置

	config->enableSlave = true;
	config->sselPol = (spi_spol_t)kSPI_SpolActiveAllLow;												// 设置片选低电平有效
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		Flex COMM 修改 SPI SLAVE 设置
//	@param		config			FC所选功能的配置参数结构体
//	@param		param_index		对应参数的索引
//	@param		data			参数数值
//	Sample usage:				zf_spi_slave_param_set( &spi_slave_config, SPI_SLAVE_PARAM_RX_FIFO, SPI_RX_FIFO_1_ENTRIE );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_slave_param_set  (spi_slave_config_t *config, spi_slave_param_list param_index, uint32_t data)
{
	assert(config != NULL);
	switch(param_index)
	{
		case SPI_SLAVE_PARAM_SLAVE_ENABLE :																// 时钟极性
			config->enableSlave = (bool) data;															// 更新时钟极性选项
			break;
		case SPI_SLAVE_PARAM_CLOCK_POLARITY :															// 时钟极性
			config->polarity = (spi_clock_polarity_t) data;												// 更新时钟极性选项
			break;
		case SPI_SLAVE_PARAM_CLOCK_PHASE :																// 时钟相位
			config->phase = (spi_clock_phase_t) data;													// 更新时钟相位选项
			break;
		case SPI_SLAVE_PARAM_DATA_DIRECTION :															// SPI 数据排列方向 MSB/LSB
			config->direction = (spi_shift_direction_t) data;											// 更新数据方向
			break;
		case SPI_SLAVE_PARAM_DATA_WIDTH :																// SPI 单个数据长度
			config->dataWidth = (spi_data_width_t) data;												// 更新单个数据长度
			break;
		case SPI_SLAVE_PARAM_SSEL_POLARITY :															// 从机有效电平
			config->sselPol = (spi_spol_t) data;														// 修改从机选择电平
			break;
		case SPI_SLAVE_PARAM_TX_FIFO :																	// TX 缓冲区触发级数
			config->txWatermark = (uint8_t) data;														// 修改接收 TX 触发条例数目
			break;
		case SPI_SLAVE_PARAM_RX_FIFO :																	// RX 缓冲区触发级数
			config->rxWatermark = (uint8_t) data;														// 修改接收 RX 触发条例数目
			break;
		default:
			break;
	}
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		Flex COMM 设置 SPI 数据格式
//	@param		flexCommIndex	所选 FC 标识
//	@param		config			FC所选功能的配置参数结构体
//	Sample usage:				zf_spi_slave_set_spi_dataformat( FLEX_COMM0, flexcomm_spi_slave_config_1 );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_slave_set_spi_dataformat (flexcomm_index_list flexCommIndex, spi_slave_config_t *config)
{
	g_spi_data_config[flexCommIndex].dataWidth = config->dataWidth;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		打开对应 FlexCOMM 端口中断使能
//	@param		flexCommIndex	所选 FC 标识
//	@param		handler(void)	指定的自拟定中断服务函数
//	Sample usage:				zf_spi_interrupt_enable( FLEX_COMM0, SPI_IRQHandler );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_interrupt_enable (flexcomm_index_list flexCommIndex, void handler(void))
{
	assert(flexCommIndex <= 7 && handler != NULL);
	flexcomm_irqn_func[flexCommIndex] = handler;
	EnableIRQ(flexcomm_irqn[flexCommIndex]);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		关闭对应 FlexCOMM 端口中断使能
//	@param		flexCommIndex	所选 FC 标识
//	@param		interrput_mode	所选中断方式
//	Sample usage:				zf_spi_interrupt_disable( FLEX_COMM0 );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_interrupt_disable (flexcomm_index_list flexCommIndex)
{
	assert(flexCommIndex <= 7);
	DisableIRQ(flexcomm_irqn[flexCommIndex]);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		修改对应 FlexCOMM 端口中断方式
//	@param		flexCommIndex	所选 FC 标识
//	@param		interrput_mode	所选中断方式
//	Sample usage:				zf_spi_interrupt_disable( FLEX_COMM0, SPI_INTERRUPT_MODE_TXLVL );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_interrupt_mode_set (flexcomm_index_list flexCommIndex, uint8_t interrput_mode)
{
	assert(flexCommIndex <= 7 && interrput_mode & 0xff);
	spi_index[flexCommIndex]->FIFOINTENSET = interrput_mode;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		Flex COMM 建立 SPI Transfer
//	@param		flexCommIndex	Flex模块号( FC0, FC1, FC2, FC3, FC4, FC5, FC6, FC7 )
//	@param		callback		指定的 transfer 回调函数 ( 中断方式传输回调 )
//	Sample usage:				zf_spi_transfer_great_handle( FLEX_COMM0, callback );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_transfer_great_handle (flexcomm_index_list flexCommIndex, spi_master_callback_t callback)
{
	assert(flexCommIndex <= 7);																			// 确认参数正确
	SPI_MasterTransferCreateHandle
	(
		spi_index[flexCommIndex],																		// 对应 USART
		&spi_transfer_handle[flexCommIndex],																// 对应处理结构体
		callback,																						// 用户定义中断处理函数
		NULL																							// 屏蔽用户中断处理函数参数
	);		
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		Flex COMM 使用 SDK spi 协议栈工作交换信息
//	@param		flexCommIndex	Flex模块号( FC0, FC1, FC2, FC3, FC4, FC5, FC6, FC7 )
//	@param		dataout			发送数据指针
//	@param		datain			接收数据指针
//	@param		datalen			数据长度
//	Sample usage:				zf_spi_transfer_great_handle( FLEX_COMM0, dataout, datain, datalen);
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_transfer_non_blocking (flexcomm_index_list flexCommIndex, uint8_t *dataout, uint8_t *datain, uint8_t datalen)
{
	g_spi_transfer_t[flexCommIndex].txData      = dataout;
	g_spi_transfer_t[flexCommIndex].rxData      = datain;
	g_spi_transfer_t[flexCommIndex].dataSize    = datalen;
	g_spi_transfer_t[flexCommIndex].configFlags = kSPI_FrameAssert;
	SPI_MasterTransferNonBlocking
	(
		spi_index[flexCommIndex],
		&spi_transfer_handle[flexCommIndex],
		&g_spi_transfer_t[flexCommIndex]
	);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		读取对应 SPI 的 FIFO 状态
//	@param		flexCommIndex	所选 FC 标识
//	Sample usage:				status = zf_spi_get_fifo_status( FLEX_COMM0 );
//-------------------------------------------------------------------------------------------------------------------
uint32_t zf_spi_get_fifo_status(flexcomm_index_list flexCommIndex)
{
	assert(flexCommIndex <= 7);
	return spi_index[flexCommIndex]->FIFOSTAT;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		读取对应 SPI 的 FIFO 状态
//	@param		flexCommIndex	所选 FC 标识
//	Sample usage:				len = zf_spi_get_fifo_TXLVL( FLEX_COMM0 );
//-------------------------------------------------------------------------------------------------------------------
uint8_t zf_spi_get_fifo_TXLVL(flexcomm_index_list flexCommIndex)
{
	assert(flexCommIndex <= 7);
	return (uint8_t)((spi_index[flexCommIndex]->FIFOSTAT & 0x00001F00) >> 8);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		读取对应 SPI 的 FIFO 状态
//	@param		flexCommIndex	所选 FC 标识
//	Sample usage:				len = zf_spi_get_fifo_RXLVL( FLEX_COMM0 );
//-------------------------------------------------------------------------------------------------------------------
uint8_t zf_spi_get_fifo_RXLVL(flexcomm_index_list flexCommIndex)
{
	assert(flexCommIndex <= 7);
	return (uint8_t)((spi_index[flexCommIndex]->FIFOSTAT & 0x001F0000) >> 16);
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		SPI MASTER 发送一段数据 忽略从机返回数据 即丢弃从机返回数据不保存到 FIFO 中
//	@param		flexCommIndex	所选 FC 标识
//	@param		data			发送内容指针
//	@param		datalen			数据长度
//	Sample usage:				zf_spi_master_write_blocking( FLEX_COMM0, &data, 8 );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_master_write_blocking (flexcomm_index_list flexCommIndex, uint16_t *data, uint16_t datalen)
{
	assert(flexCommIndex <= 7 && data != NULL);															// 确认参数正确
	spi_index[flexCommIndex]->FIFOCFG |= 0x00030000;													// 清空发送及接收 FIFO buffer
	while(datalen > 0)
	{
		if (SPI_GetStatusFlags(spi_index[flexCommIndex]) & kSPI_TxNotFullFlag)							// 发送 FIFO 未满
		{
			if(datalen > 1)
			{
				*(FIFOWR_SPI_H16[flexCommIndex]) = 														// 对应 SPI 的 FIFOWR 寄存器地址
				(
					0x0060 | (g_spi_data_config[flexCommIndex].dataWidth << 8) |						// 设置 接收忽略 帧结束 数据位数
					(~(0x1 << g_spi_data_config[flexCommIndex].sselNum) & 0x0f)							// 选择从机
				);

				spi_index[flexCommIndex]->FIFOWR |= *data++;											// 写入数据
				datalen --;																				// 数据计数自减
			}
			else
			{
				*(FIFOWR_SPI_H16[flexCommIndex]) = 	 													// 对应 SPI 的 FIFOWR 寄存器地址
				(
					0x0070 | (g_spi_data_config[flexCommIndex].dataWidth << 8) |						// 设置 接收忽略 传输结束 数据位数
					(~(0x1 << g_spi_data_config[flexCommIndex].sselNum) & 0x0f)							// 选择从机
				);

				spi_index[flexCommIndex]->FIFOWR |= *data;												// 写入数据
				datalen --;																				// 数据计数自减
			}
		}
	}
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		SPI MASTER 发送一段数据 忽略从机返回数据 即丢弃从机返回数据不保存到 FIFO 中
//	@param		flexCommIndex	所选 FC 标识
//	@param		data			发送内容指针
//	@param		datalen			数据长度
//	Sample usage:				zf_spi_master_read_blocking( FLEX_COMM0, &data, 8 );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_master_read_blocking (flexcomm_index_list flexCommIndex, uint16_t *data, uint16_t datalen)
{
	uint8_t receive_count = datalen;
	assert(flexCommIndex <= 7 && data != NULL);															// 确认参数正确
	spi_index[flexCommIndex]->FIFOCFG |= 0x00030000;													// 清空发送及接收 FIFO buffer

	while(datalen || receive_count)																		// 检查是否达到 发送 接收 完成
	{
		// ============================ send data part ============================
		if( datalen > 1 )
		{
			if (SPI_GetStatusFlags(spi_index[flexCommIndex]) & kSPI_TxNotFullFlag)						// 发送 FIFO 未满
			{
				*(FIFOWR_SPI_H16[flexCommIndex]) = 														// 对应 SPI 的 FIFOWR 寄存器地址
				(
					0x0020 | (g_spi_data_config[flexCommIndex].dataWidth << 8) |						// 设置 帧结束 数据位数
					(~(0x1 << g_spi_data_config[flexCommIndex].sselNum) & 0x0f)							// 选择从机
				);

				spi_index[flexCommIndex]->FIFOWR |= 0x0000;												// 发送数据写为 0x0000
				datalen --;																				// 发送计数自减
			}
		}
		else if(datalen == 1)
		{
			if (SPI_GetStatusFlags(spi_index[flexCommIndex]) & kSPI_TxNotFullFlag)						// 发送 FIFO 未满
			{
				*(FIFOWR_SPI_H16[flexCommIndex]) = 														// 对应 SPI 的 FIFOWR 寄存器地址
				(
					0x0030 | (g_spi_data_config[flexCommIndex].dataWidth << 8) |						// 设置 传输结束 数据位数
					(~(0x1 << g_spi_data_config[flexCommIndex].sselNum) & 0x0f)							// 选择从机
				);

				spi_index[flexCommIndex]->FIFOWR |= 0x0000;												// 发送数据写为 0x0000
				datalen --;																				// 发送计数自减
			}
		}
		// ============================ send data part ============================

		// ========================== receive data part ==========================
		if(SPI_GetStatusFlags(spi_index[flexCommIndex]) & kSPI_RxNotEmptyFlag)							// 接收 FIFO 不为空
		{
			*data++ = spi_index[flexCommIndex]->FIFORD;													// 读取 FIFO buffer 数据
			receive_count --;																			// 接收计数自减
		}
		// ========================== receive data part ==========================
	}
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		SPI MASTER 发送一段数据 并读取从机返回数据
//	@param		flexCommIndex	所选 FC 标识
//	@param		dataout			发送内容指针
//	@param		datain			接收内容指针
//	@param		datalen			数据长度
//	Sample usage:				zf_spi_master_transfer_blocking( FLEX_COMM0, &data, 8, Data16Bits, SSEL0 );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_master_transfer_blocking (flexcomm_index_list flexCommIndex, uint16_t *dataout, uint16_t *datain, uint16_t datalen )
{
	uint8_t receive_count = datalen;
	assert(flexCommIndex <= 7 && dataout != NULL && datain != NULL);
	spi_index[flexCommIndex]->FIFOCFG |= 0x00030000;													// 清空发送及接收 FIFO buffer

	while(datalen || receive_count)																		// 检查是否达到 发送 接收 完成
	{
		// ============================ send data part ============================
		if(datalen > 1)
		{
			if (SPI_GetStatusFlags(spi_index[flexCommIndex]) & kSPI_TxNotFullFlag) 						// 发送 FIFO 未满
			{
				*(FIFOWR_SPI_H16[flexCommIndex]) = 														// 对应 SPI 的 FIFOWR 寄存器地址
				(
					0x0020 | (g_spi_data_config[flexCommIndex].dataWidth << 8) |						// 设置 帧结束 数据位数
					(~(0x1 << g_spi_data_config[flexCommIndex].sselNum) & 0x0f)							// 选择从机
				);

				spi_index[flexCommIndex]->FIFOWR |= *dataout++;											// 发送数据写为 0x0000
				datalen --;																				// 发送计数自减
			}
		}
		else if(datalen == 1)
		{
			if (SPI_GetStatusFlags(spi_index[flexCommIndex]) & kSPI_TxNotFullFlag)						// 发送 FIFO 未满
			{
				*(FIFOWR_SPI_H16[flexCommIndex]) = 														// 对应 SPI 的 FIFOWR 寄存器地址
				(
					0x0030 | (g_spi_data_config[flexCommIndex].dataWidth << 8) |						// 设置 传输结束 数据位数
					(~(0x1 << g_spi_data_config[flexCommIndex].sselNum) & 0x0f)							// 选择从机
				);

				spi_index[flexCommIndex]->FIFOWR |= *dataout++;											// 发送数据写为 0x0000
				datalen --;																				// 发送计数自减
			}
		}
		// ============================ send data part ============================

		// ========================== receive data part ==========================
		if(SPI_GetStatusFlags(spi_index[flexCommIndex]) & kSPI_RxNotEmptyFlag)							// 接收 FIFO 不为空
		{
			*datain++ = spi_index[flexCommIndex]->FIFORD;												// 读取 FIFO buffer 数据
			receive_count --;																			// 接收计数自减
		}
		// ========================== receive data part ==========================
	}
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		SPI SLAVE 发送一段数据 忽略主机发送数据 即丢弃主机发送数据不保存到 FIFO 中
//	@param		flexCommIndex	所选 FC 标识
//	@param		data			发送内容指针
//	Sample usage:				zf_spi_slave_write_blocking( FLEX_COMM0, &data, 8 );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_slave_write_blocking (flexcomm_index_list flexCommIndex, uint16_t *data, uint16_t datalen)
{
	assert(flexCommIndex <= 7 && data != NULL);
	spi_index[flexCommIndex]->FIFOCFG |= 0x00030000;													// 清空发送及接收 FIFO buffer
	while(datalen > 0)
	{
		if (SPI_GetStatusFlags(spi_index[flexCommIndex]) & kSPI_TxNotFullFlag)							// 发送 FIFO 未满
		{
			if(datalen > 1)
			{
				*(FIFOWR_SPI_H16[flexCommIndex]) = 
				( 0x0060 | (g_spi_data_config[flexCommIndex].dataWidth << 8));							// 设置 接收忽略 帧结束 数据位数
				spi_index[flexCommIndex]->FIFOWR |= *data++;											// 写入发送数据
				datalen --;
			}
			else
			{
				*(FIFOWR_SPI_H16[flexCommIndex]) =
				( 0x0070 | (g_spi_data_config[flexCommIndex].dataWidth << 8));							// 设置 接收忽略 帧结束 传输结束 数据位数
				spi_index[flexCommIndex]->FIFOWR |= *data;												// 写入发送数据
				datalen --;
			}
		}
	}
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		SPI SLAVE 发送一段数据 并接收主机发送数据 即主机发送数据保存到 FIFO 中
//	@param		flexCommIndex	所选 FC 标识
//	@param		dataout			发送内容指针
//	@param		datain			接收内容指针
//	Sample usage:				zf_spi_slave_transfer_blocking( FLEX_COMM0, &dataout, &datain, 8 );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_slave_transfer_blocking (flexcomm_index_list flexCommIndex, uint16_t *dataout, uint16_t *datain, uint16_t datalen)
{
	uint8_t receive_count = datalen;
	assert(flexCommIndex <= 7 && dataout != NULL && datain != NULL);
	spi_index[flexCommIndex]->FIFOCFG |= 0x00030000;													// 清空发送及接收 FIFO buffer

	while(datalen || receive_count)																		// 检查是否达到 发送 接收 完成
	{
		// ============================ send data part ============================
		if( datalen >= 1 )
		{
			if (SPI_GetStatusFlags(spi_index[flexCommIndex]) & kSPI_TxNotFullFlag) 						// 发送 FIFO 未满
			{
				*(FIFOWR_SPI_H16[flexCommIndex]) =
				( 0x0020 | (g_spi_data_config[flexCommIndex].dataWidth << 8));							// 设置 帧结束 数据位数

				spi_index[flexCommIndex]->FIFOWR |= *dataout++;											// 发送数据
				datalen --;																				// 发送计数自减
			}
		}
		else if(datalen == 1)
		{
			if (SPI_GetStatusFlags(spi_index[flexCommIndex]) & kSPI_TxNotFullFlag)						// 发送 FIFO 未满
			{
				*(FIFOWR_SPI_H16[flexCommIndex]) =
				( 0x0030 | (g_spi_data_config[flexCommIndex].dataWidth << 8));							// 设置 帧结束 传输结束 数据位数

				spi_index[flexCommIndex]->FIFOWR |= *dataout++;											// 发送数据写为 0x0000
				datalen --;																				// 发送计数自减
			}
		}
		// ============================ send data part ============================

		// ========================== receive data part ==========================
		if(SPI_GetStatusFlags(spi_index[flexCommIndex]) & kSPI_RxNotEmptyFlag)							// 接收 FIFO 不为空
		{
			*datain++ = spi_index[flexCommIndex]->FIFORD;												// 读取 FIFO buffer 数据
			receive_count --;																			// 接收计数自减
		}
		// ========================== receive data part ==========================
	}
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		SPI SLAVE 停止输出数据 即默认主机读取到全部为 0x0000
//	@param		flexCommIndex	所选 FC 标识
//	Sample usage:				zf_spi_slave_write_lock( FLEX_COMM0, &data, Data16Bits );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_slave_write_lock (flexcomm_index_list flexCommIndex)
{
	spi_index[flexCommIndex]->FIFOCFG |= 0x00030000;													// 清空发送及接收 FIFO buffer
	*(FIFOWR_SPI_H16[flexCommIndex]) =
	(0x00B0 | (g_spi_data_config[flexCommIndex].dataWidth << 8));
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		以 16bit 方式读取 FIFO 中的数据 <如果 FIFO 中有数据的话>
//	@param		flexCommIndex	所选 FC 标识
//	@param		data			接收内容指针
//	@return		result			是否接收到数据 0-没接收到 n-接收到数据个数
//	Sample usage:				zf_spi_read_fifo( FLEX_COMM0, &data );
//-------------------------------------------------------------------------------------------------------------------
uint8_t zf_spi_read_fifo (flexcomm_index_list flexCommIndex, uint16_t *data)
{
	uint8_t 
	result = 0;
	assert(flexCommIndex <= 7 && data != NULL);
	while (SPI_GetStatusFlags(spi_index[flexCommIndex]) & kSPI_RxNotEmptyFlag)
	{
		result ++;
		*data++ = spi_index[flexCommIndex]->FIFORD;
	}
	return result;
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		以 16bit 方式读取 FIFO 中的数据 <如果 FIFO 中有数据的话>
//	@param		flexCommIndex	所选 FC 标识
//	@return		result			是否接收到数据 0-没接收到 n-接收到数据个数
//	Sample usage:				zf_spi_read_data( FLEX_COMM0 );
//-------------------------------------------------------------------------------------------------------------------
uint16_t zf_spi_read_data (flexcomm_index_list flexCommIndex)
{
	assert(flexCommIndex <= 7);
	return spi_index[flexCommIndex]->FIFORD;

}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		主机往 FIFO 写入一个数据
//	@param		flexCommIndex	所选 FC 标识
//	@return		data			写入的数据
//	@return		config			配置
//	Sample usage:				zf_spi_master_write_data( FLEX_COMM0, data, SPI_FIFO_WIRTE_EOT );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_master_write_data (flexcomm_index_list flexCommIndex, uint16_t data, uint16_t config)
{
	assert(flexCommIndex <= 7);

	*(FIFOWR_SPI_H16[flexCommIndex]) = 																	// 对应 SPI 的 FIFOWR 寄存器地址
	(
		config | (g_spi_data_config[flexCommIndex].dataWidth << 8) |									// 设置 帧结束 数据位数
		(~(0x1 << g_spi_data_config[flexCommIndex].sselNum) & 0x0f)										// 选择从机
	);

	spi_index[flexCommIndex]->FIFOWR |= data;															// 发送数据
}

//-------------------------------------------------------------------------------------------------------------------
//	@brief		从机往 FIFO 写入一个数据
//	@param		flexCommIndex	所选 FC 标识
//	@return		data			写入的数据
//	@return		config			配置
//	Sample usage:				zf_spi_slave_write_data( FLEX_COMM0, data, SPI_FIFO_WIRTE_EOT );
//-------------------------------------------------------------------------------------------------------------------
void zf_spi_slave_write_data (flexcomm_index_list flexCommIndex, uint16_t data, uint16_t config)
{
	assert(flexCommIndex <= 7);

	*(FIFOWR_SPI_H16[flexCommIndex]) = 																	// 对应 SPI 的 FIFOWR 寄存器地址
	(
		config | (g_spi_data_config[flexCommIndex].dataWidth << 8)										// 设置 帧结束 数据位数
	);

	spi_index[flexCommIndex]->FIFOWR |= data;															// 发送数据
}


